package ar.uba.is2.ec.matem;

import java.util.Collection;

import org.apache.log4j.Logger;

import ar.uba.is2.common.threads.ThreadManager;
import ar.uba.is2.ec.config.Contexto;
import ar.uba.is2.ec.matem.exec.Despachador;
import ar.uba.is2.ec.matem.exec.impl.DespachadorSimple;
import ar.uba.is2.ec.matem.modelo.ContextoDeModelo;
import ar.uba.is2.ec.matem.modelo.ModeloEjecutable;
import ar.uba.is2.ec.matem.modelo.ModeloEjecutableFactory;
import ar.uba.is2.ec.matem.modelo.ModeloMatematico;

public class ModelRunner implements Runnable {
	
	private static final Logger logger = Logger.getLogger(ModelRunner.class);

	private ModeloEjecutableFactory modeloEjecutableFactory = ModeloEjecutableFactory.instance;
	private Despachador despachador = DespachadorSimple.getInstance();

	private ModeloMatematico modelo;
	private ContextoDeModelo contextoDeModelo;
	
	private long waitTime;
	
	public ModelRunner(ModeloMatematico modelo, ContextoDeModelo contextoDeModelo) {
		this.modelo = modelo;
		this.contextoDeModelo = contextoDeModelo;
		this.waitTime = Long.parseLong(Contexto.instance.get("ec.modelo.matematico.runner.time"));
	}
	
	public void correr() {
		ThreadManager.instance.crearYCorrerThread(this);
	}
	
	@Override
	public void run() {
		
		while (true) {
		
			Collection<ModeloMatematico> submodelos = obtenerSubmodelos();
	
			for (ModeloMatematico submodelo : submodelos) {
				
				ModeloEjecutable modelo = construirModeloEjecutable(submodelo);
				
				despacharModelo(modelo);
			}

			synchronized (this) {
				try {
					this.wait(this.waitTime);
				} catch (InterruptedException e) {
					break;
				}
			}
		}
	}

	private ModeloEjecutable construirModeloEjecutable(ModeloMatematico submodelo) {
		return this.modeloEjecutableFactory.construirModeloEjecutable(submodelo);
	}

	private void despacharModelo(ModeloEjecutable modelo) {
		this.despachador.despachar(modelo);
	}

	private Collection<ModeloMatematico> obtenerSubmodelos() {
		int cantProc  = 1;
		try {
			cantProc = Integer.parseInt(Contexto.instance.get("ec.modelo.matematico.exec.proc"));
		} catch (NumberFormatException e) {
			logger.warn("Error al leer la cantidad de procesadores. Usando valor por default");
		}
		
		return contextoDeModelo.obtenerSubmodelos(this.modelo, cantProc);
	}

	
}
